
#include <pic18.h>
#include "main.h"



typedef union 
{
		unsigned long LONG;
		struct 
		{	
				unsigned char b0;
				unsigned char b1;
				unsigned char b2;
				unsigned LSB : 4;
				unsigned MSB : 4;		
		}BYTE;
		
} BCD_NUMBER;



int errno = 0;

char isupper( char c )
{
	return ( c >='A' && c <= 'Z' );
}

char isalpha( char c )
{
	return ( (c >= 'a' && c <= 'z')  || isupper(c) );
}

char isspace( char c )
{
	return ( c == ' ' || (c <= 015 && c >= 011) );
}

char isdigit( char c )
{
	return ( c >= '0' && c <= '9' );
}

char StrIsPrintableChar ( char Char )
{
	return ( isdigit(Char) || isalpha(Char) );
}

int StrLen( const char *s )
{
	int Length = 0;

	if ( s != NULL )
	{
		while ( *s++ )
		{
			if ( ++Length > 1024 )
				return ( -1); 
		}
	}	

	return Length; 
}

/* return: pointer of the Char position; in errno will be offset of the Char */
unsigned char* FindChar ( unsigned char* Str, unsigned char Ch )
{
	unsigned char* s = Str;
	errno = 0;


	while (  *Str != 0 && *Str != Ch )
	{
		if ( ++errno > 1024 )
		{
			errno = (-1);
			return s;
		}
		Str++;
	}
	
	if ( *Str == 0 )
	{
		errno = (-1);
		return s;
	}
	
	return Str;
}

/* /\* return: offset of next Position after the Char; Number - Char by order *\/ */
/* int FindCharNumber ( unsigned char* Str, unsigned char Ch, unsigned char Number ) */
/* { */
/* 	errno = 0; */

/* 	while ( *Str ) */
/* 	{ */
/* 		if ( ++errno > 1024 ) */
/* 		{ */
/* 			return (-1); */
/* 		} */

/* 		if ( *Str == Ch ) */
/* 		{ */
/* 			if ( --Number == 0 ) */
/* 				return errno; */
/* 		} */
/* 		Str++; */
/* 	} */
	
/* 	return (-1); */
/* } */


/* return: pointer of next Position after the Char; Number - Char by order */
unsigned char* FindCharNumber ( unsigned char* Str, unsigned char Ch, unsigned char Number )
{
	errno = 0;

	while ( *Str )
	{
		if ( ++errno > 1024 )
		{
			return (NULL);
		}

		if ( *Str == Ch )
		{
			if ( --Number == 0 )
				return ++Str;
		}
		Str++;
	}
	
	return (NULL);
}
 
/* return TRUE if all string contain the same char - Ch */
unsigned char Str_If_All_Set( unsigned char* Str, unsigned char Ch )
{
	while ( *Str == Ch && *Str != 0 )
	{
		*Str++;
	}

	if ( *Str == 0 )
		return TRUE;
	return FALSE;
}

/* return: position of replaced char */
int StrReplaceChar ( unsigned char* Str, unsigned char Ch, unsigned char Replace ) 
{
	int end_of_line;
	
	FindChar( Str, Ch);
	
	end_of_line = errno;

	if ( end_of_line != (-1) )
	{
		Str[end_of_line] = Replace;
	} 
	else
		return ( -1);

	return end_of_line;
}

/* return: how many characters was replaced */
int StrReplaceCharAll ( unsigned char* Str, unsigned char Ch, unsigned char Replace )
{
	unsigned char CharAmount = 0;
	errno = 0;

	while (  *Str )
	{
		if ( ++errno > 1024 )
		{
			return (-1);
		}

		if ( *Str == Ch )
		{
			*Str = Replace;
			CharAmount++;
		}
		Str++;
	}

	return CharAmount;					  /* how many characters was replaced */
} 

long StrToLong( const char* s )
{
	register char	c;
	register long	a;
	register unsigned char sign;
	
	//errno = NO_ERR;
	errno = 0;
		a = 0;
	sign = 0;

  skipws:
	c = *s;
	if( ( c < '0' || c > '9' ) && ( c != '-' ) ) 
	{
		if ( c == 0 ) //end of string
		{
			//errno = NO_NUMBER;
			return (-1);
		}
		a = 0;
		sign = 0;
		s++;
		errno++;
		goto skipws;
	}

	if(c == '-') 
	{
		sign++;
		s++;
		errno++;
		goto skipws;
	} 
	else 
		if(c == '+')
		{
			s++;
			errno++;
			goto skipws;			
		}

  conv:
	c = *s;
	if ( c == '.' )				  /* skip a point */
	{
		s++;
		errno++;
		goto conv;
	}

	if( c >= '0' && c <= '9') 
	{
		a = a*10L + (c - '0');
		s++;
		errno++;
		goto conv;
	}

	if(sign)
		return -a;
	
	return a;
}

char* LongToStr( unsigned char* s, unsigned long Val  )
{
	unsigned char Digit = 0, i = 8, p = 0;//, begin = 0;

	while( 1)
	{
		while ( Val >= Exp[i] )
		{
			Val -= Exp[i];
			Digit++;
			//begin++;
		}

		//if ( Digit || begin )
		if ( Digit || p )
			s[p++] = Digit + '0';

		Digit = 0;

		if ( i-- == 0 )
			break;
	}
	
	s[p++] = Val + '0';
	s[p] = 0;

	return s; 
}

char* ByteToStr_10( unsigned char* s, unsigned long Val  )
{
	unsigned char Digit = 0, p = 0;
 
	while ( Val >= 10 )
	{
		Val -= 10;
		Digit++;
	}

//	Digit = Val/10;

	s[p++] = Digit + '0';
	
	Digit = 0;
	
	s[p++] = Val + '0';
	s[p] = 0;

	return s; 
}

/* Lond with point. Example: Val=12 -> 0.12; Val = 309 -> 3.09; Val = 234789 -> 2347.89*/
char* Long_pToStr( unsigned char* s, unsigned long Val  )
{
	unsigned char Digit = 0, i = 8, p = 0, begin = 0;

	while( 1)
	{
		if ( Exp[i] == 10 )
		{
			if ( begin == 0 )
				s[p++] = '0';
			s[p++] = '.';
		}	
		while ( Val >= Exp[i] )
		{
			Val -= Exp[i];
			Digit++;
			begin = 1;
		}

		if ( Digit || begin )
			s[p++] = Digit + '0';

		Digit = 0;

		if ( i-- == 0 )
			break;
	}
	
	if ( begin == 0 )
		s[p++] = '0';
	s[p++] = Val + '0';
	s[p] = 0;
	return s;
}


int StrCmp( register const char * s1, register const char * s2 )
{
	register signed int Result;
	
	errno = 0;
	
	while( !(Result = (unsigned char)*s1 - (unsigned char)*s2++) && *s1++ )
		errno++;

	return Result;
}

/* if return FALSE in errno variable - number of bytes was coincidence */
//unsigned char StrCmp ( const unsigned char *s1, unsigned char *s2 )
/* unsigned char StrCmp ( const unsigned char *s1, const unsigned char *s2 ) */
/* { */
/* 	errno = 0; */
/* 	while ( *s1 ) */
/* 	{ */
/* 		if ( *s1++ != *s2++) */
/* 			return FALSE; */
/* 		errno++; */
/* 	} */
/* 	if ( *s2 == 0 ) */
/* 		return TRUE; */
/* 	return FALSE; */
/* } */

int MemCmp ( unsigned char* s1, unsigned char* s2, unsigned char BytesNumber )
{
	register signed int Result;
	
	errno = 0;
	
	while( BytesNumber-- )
	{
		if ( Result = (unsigned char)*s1++ - (unsigned char)*s2++ ) 
			break;
		errno++;
	}

	return Result; 
}

/* /\* if return FALSE in errno variable - number of bytes was coincidence *\/ */
/* unsigned char MemCmp ( const unsigned char *s1, unsigned char *s2, unsigned char BytesNumber ) */
/* { */
/* 	errno = 0; */
/* 	while ( BytesNumber ) */
/* 	{ */
/* 		if ( *s1++ != *s2++) */
/* 			return FALSE; */
/* 		errno++; */
/* 		BytesNumber--; */
/* 	} */

/* 	return TRUE;  */
/* } */

unsigned char* MemCpy ( unsigned char *m1, unsigned char *m2, unsigned char ByteNumber )
{
	unsigned char i;
	for ( i = 0; i < ByteNumber; i++ )
	{
		m1[i] = m2[i];
	}
	return m1; 
}
 
unsigned char* StrCpy ( unsigned char *s1, const char *s2 )
{
	errno = 0;
	
	while(*s1++ = *s2++ )
	{
		if ( ++errno > 1024 )
			return (NULL);
	}

	return s1;
}

/* return pointer on the next char after Ch */
unsigned char* StrCpy_UpTo_Ch ( unsigned char *s1, const char *s2, unsigned char Ch )
{
	errno = 0;

	while ( *s2 != Ch )
	{
		*s1 = *s2;

		if ( *s1 == 0 )
			return (NULL);			  /* ERROR: Ch - not found */
		
		*s1++;
		*s2++;

		if ( ++errno > 1024 )
			return (NULL);
	} 

	*s1 = 0;

	return (unsigned char*)(++s2);					  /* next char after the Ch */
}



void MemSet ( unsigned char *m, unsigned char ByteNumber, unsigned char FillByte )
{
	while ( ByteNumber )
	{
		m[ByteNumber-1] = FillByte;
		ByteNumber--;
	}
} 


/* unsigned char* StrnCat(unsigned char* to, const unsigned char* from, unsigned char size) */
/* { */
/* 	char* cp; */
/* 	cp = to; */

/* 	while(*cp) */
/* 		cp++; */

/* 	while(size && (*cp++ = *from++)) */
/* 		size--; */

/* 	if(size == 0) */
/* 		*cp = 0; */

/* 	return to; */
/* } */


unsigned char* StrCat(  unsigned char* to, const unsigned char* from )
{
	unsigned char* cp;

	cp = to;

	while( *cp )
		cp++;

	while( *cp++ = *from++ )
		continue;

	return to;
}

char* StrCat_UpTo_Ch(  char* to, const char* from, unsigned char Ch )
{
	char* cp;

	cp = to;

	while( *cp )
		cp++;

	while( *from != Ch )
	{
		*cp++ = *from++;
	}
		
	*cp = 0;

	return to;
}


 
/* /\* return index of first found NUMBER. Example: "ABCD 2345Sa" return: 5 *\/ */
/* int StrFindFirstNumber ( unsigned char* Str ) */
/* { */
/* 	unsigned char i = 0; */

/* 	while ( 1) */
/* 	{ */
/* 		if ( (*Str >= '0' && *Str <= '9') || *Str == 0 ) */
/* 			break; */
/* 		i++; */
/* 	} */

/* 	if ( *Str == 0 ) */
/* 		return (-1);  */

/* 	return i; */
/* } */
 
unsigned char CharToNumber( unsigned char Char )
{
	//if ( Char == 0 || Char > '9' || Char < '0' )
	if ( Char > '9' || Char < '0' )
		return 0xFF; 				  

	return (Char - '0');
}


unsigned long StrToBCD_Long( unsigned char* Str )
{
	unsigned char temp;
	unsigned long BCD = 0xFFFFFFFF;

	while ( (temp = CharToNumber(*Str++)) != 0xFF )
	{
		BCD <<= 4;
		BCD += temp;
	}
	
	return BCD; 
}

unsigned char* BCD_ToStr( unsigned char* Str, unsigned long BCD )
{
	unsigned char temp, i;
	BCD_NUMBER BCD_Num;
	
	BCD_Num.LONG = BCD;
	
	for ( i = 0; i < 8; i++ )
	{
		temp = BCD_Num.BYTE.MSB;
		if ( temp <= 9 ) 
		{
			*Str++ = (temp + '0' );
		}
		BCD_Num.LONG <<= 4;
	}

	*Str = 0;

	return Str; 
}

unsigned char* HexToChar( unsigned char* Char, unsigned char* Hex, unsigned char HexCount )
{
	unsigned char temp;
	//errno = 0;

	while ( HexCount-- )
	{ 
		temp = *Hex >> 4;
		if ( temp >= 10 )
			temp = temp + 'A' -10;  
		else
			temp += '0';

		*Char++ = temp;  
	
		temp = *Hex & 0x0F;
		if ( temp >= 10 )
			temp = temp + 'A' -10;
		else
			temp += '0';

		*Char++ = temp;

		Hex++;

	}

	*Char = 0;
	return Char;  
} 

unsigned char* CharToHex( unsigned char* Hex, unsigned char* Char )
{
	unsigned char temp;

	errno = 0;
	
	while ( *Char >= ' ' )
	{
		temp = *Char++;
		if ( temp >= 'A' )
			temp = (temp - 'A') + 10;
		else
			temp -= '0';

		*Hex = temp<<4;

		temp = *Char++;
		if ( temp >= 'A' )
			temp = (temp - 'A') + 10;
		else
			temp -= '0';
		
	   *Hex |= temp; 
		
		errno++;
		Hex++;
	}

	return Hex; 
}

unsigned char* CharnToHex( unsigned char* Hex, unsigned char* Char, unsigned char ByteCount )
{
	unsigned char temp;

	errno = 0;
	
	while ( *Char >= ' ' )
	{
		temp = *Char++;
		if ( temp >= 'A' )
			temp = (temp - 'A') + 10;
		else
			temp -= '0';

		*Hex = temp<<4;

		temp = *Char++;
		if ( temp >= 'A' )
			temp = (temp - 'A') + 10;
		else
			temp -= '0';
		
	   *Hex |= temp;
		
		errno++;
		Hex++;

		if ( --ByteCount == 0 )
			break;
	}

	return Hex;
}

unsigned char* StrToBCD ( unsigned char* Str_BCD, unsigned char* Str, unsigned char Str_BCD_Len )
{
	unsigned char sl = StrLen(Str), i;
	unsigned int a = 0;
	
	MemSet(Str_BCD, Str_BCD_Len, 0xFF );
	
	if ( sl & 0x01 )
	{
		a = 'F';
		a |= *Str++ << 8;
		i = (sl >> 1) +1;
		CharnToHex( &Str_BCD[Str_BCD_Len-i], (unsigned char*)&a, 1 );
	}

	i = Str_BCD_Len-(sl >> 1);
	CharnToHex( (Str_BCD + i), Str, Str_BCD_Len );

	return Str_BCD;
}

void FlipFlop ( unsigned char* Str )
{
	unsigned char tmp, p1 = 0 , p2 = StrLen(Str)-1;
	unsigned char c = p2>>1;

	while ( 1 )
	{
		tmp = Str[p1];
		Str[p1] = Str[p2];
		Str[p2] = tmp;
	
		if ( p1 < c )
		{
			p1++;
			p2--;
		}	
		else
			return;
	}
}

void FlipFlopN ( unsigned char* Str, unsigned char Len )
{
	unsigned char tmp, p1 = 0 , p2 = Len-1;
	unsigned char c = p2>>1;

	while ( 1 )
	{
		tmp = Str[p1];
		Str[p1] = Str[p2];
		Str[p2] = tmp;
	
		if ( p1 < c )
		{
			p1++;
			p2--;
		}	
		else
			return;
	}
}

void FlipFlopByte ( unsigned char* Byte )
{
	unsigned char tmp = *Byte, i=8;
	
	while( i )
	{
		if ( tmp & 0x01 )
			*Byte |= 1;
		if ( --i == 0 )
		   break;	
		
		*Byte <<=1;
		tmp >>= 1;
	}
}


unsigned char* BCDToStr( unsigned char* Str, unsigned char* BCD, unsigned char BCD_Len )
{
	unsigned char temp;
	//errno = 0;
 
	while ( BCD_Len-- )
	{
		temp = *BCD >> 4;
		if ( temp < 10 )
		{
			temp += '0';
			*Str++ = temp;
		}
		else
			if ( temp == 0x0B )	  /* '+' = 0x2B in ASCII code */
			{
				*Str++ = '+';
			}
	
		temp = *BCD & 0x0F;
		if ( temp < 10 )
		{
			temp += '0';
			*Str++ = temp;
		}
		else
			if ( temp == 0x0B )
			{
				*Str++ = '+';
			}

		BCD++;
	}

	*Str = 0;
	return Str;
}

unsigned char* StrCutBetweenChars( unsigned char* Destination, unsigned char* Source, unsigned char Char )
{
	errno = 0;

	while(*Source && (*Source++ != Char) )
		continue;

	if ( *Source == 0 )
	{
		return NULL;	
	}
	

	while( *Source && (*Source != Char) ) 
	{
		*Destination++ = *Source++; 	
		errno++;
	}
	
	*Destination = '\0';
   
   if ( *Source != 0 )
   {
	   return (++Source);
	} 
   return Source;	
}
